{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "6d1ca9ac",
   "metadata": {},
   "source": [
    "<a href=\"https://colab.research.google.com/github/run-llama/llama_index/blob/main/docs/examples/llm/oci_data_science.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9e3a8796-edc8-43f2-94ad-fe4fb20d70ed",
   "metadata": {},
   "source": [
    "# Oracle Cloud Infrastructure Data Science \n",
    "\n",
    "Oracle Cloud Infrastructure [(OCI) Data Science](https://www.oracle.com/artificial-intelligence/data-science) is a fully managed, serverless platform for data science teams to build, train, and manage machine learning models in Oracle Cloud Infrastructure.\n",
    "\n",
    "It offers [AI Quick Actions](https://docs.oracle.com/en-us/iaas/data-science/using/ai-quick-actions.htm), which can be used to deploy, evaluate, and fine-tune foundation LLM models in OCI Data Science. AI Quick Actions target users who want to quickly leverage the capabilities of AI. They aim to expand the reach of foundation models to a broader set of users by providing a streamlined, code-free, and efficient environment for working with foundation models. AI Quick Actions can be accessed from the Data Science Notebook.\n",
    "\n",
    "Detailed documentation on how to deploy LLM models in OCI Data Science using AI Quick Actions is available [here](https://github.com/oracle-samples/oci-data-science-ai-samples/blob/main/ai-quick-actions/model-deployment-tips.md) and [here](https://docs.oracle.com/en-us/iaas/data-science/using/ai-quick-actions-model-deploy.htm).\n",
    "\n",
    "This notebook explains how to use OCI's Data Science models with LlamaIndex."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3802e8c4",
   "metadata": {},
   "source": [
    "## Setup\n",
    "\n",
    "If you're opening this Notebook on colab, you will probably need to install LlamaIndex 🦙."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bb0dd8c9",
   "metadata": {},
   "outputs": [],
   "source": [
    "%pip install llama-index-llms-oci-data-science"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "544d49f9",
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install llama-index"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c2921307",
   "metadata": {},
   "source": [
    "You will also need to install the [oracle-ads](https://accelerated-data-science.readthedocs.io/en/latest/index.html) SDK."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "378d5179",
   "metadata": {},
   "outputs": [],
   "source": [
    "!pip install -U oracle-ads"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "737b5293",
   "metadata": {},
   "source": [
    "## Authentication\n",
    "The authentication methods supported for LlamaIndex are equivalent to those used with other OCI services and follow the standard SDK authentication methods, specifically API Key, session token, instance principal, and resource principal. More details can be found [here](https://accelerated-data-science.readthedocs.io/en/latest/user_guide/cli/authentication.html). Make sure to have the required [policies](https://docs.oracle.com/en-us/iaas/data-science/using/model-dep-policies-auth.htm) to access the OCI Data Science Model Deployment endpoint. The [oracle-ads](https://accelerated-data-science.readthedocs.io/en/latest/index.html) helps to simplify the authentication within OCI Data Science."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "03d4024a",
   "metadata": {},
   "source": [
    "## Basic Usage\n",
    "\n",
    "Using LLMs offered by OCI Data Science AI with LlamaIndex only requires you to initialize the `OCIDataScience` interface with your Data Science Model Deployment endpoint and model ID. By default the all deployed models in AI Quick Actions get `odsc-model` ID. However this ID cna be changed during the deployment."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ead155e-b8bd-46f9-ab9b-28fc009361dd",
   "metadata": {},
   "source": [
    "#### Call `complete` with a prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "60be18ae-c957-4ac2-a58a-0652e18ee6d6",
   "metadata": {},
   "outputs": [],
   "source": [
    "import ads\n",
    "from llama_index.llms.oci_data_science import OCIDataScience\n",
    "\n",
    "ads.set_auth(auth=\"security_token\", profile=\"<replace-with-your-profile>\")\n",
    "\n",
    "llm = OCIDataScience(\n",
    "    model=\"odsc-llm\",\n",
    "    endpoint=\"https://<MD_OCID>/predict\",\n",
    ")\n",
    "response = llm.complete(\"Tell me a joke\")\n",
    "\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c1f3fcbd",
   "metadata": {},
   "source": [
    "### Call `chat` with a list of messages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a80c9f6e",
   "metadata": {},
   "outputs": [],
   "source": [
    "import ads\n",
    "from llama_index.llms.oci_data_science import OCIDataScience\n",
    "from llama_index.core.base.llms.types import ChatMessage\n",
    "\n",
    "ads.set_auth(auth=\"security_token\", profile=\"<replace-with-your-profile>\")\n",
    "\n",
    "llm = OCIDataScience(\n",
    "    model=\"odsc-llm\",\n",
    "    endpoint=\"https://<MD_OCID>/predict\",\n",
    ")\n",
    "response = llm.chat(\n",
    "    [\n",
    "        ChatMessage(role=\"user\", content=\"Tell me a joke\"),\n",
    "        ChatMessage(\n",
    "            role=\"assistant\", content=\"Why did the chicken cross the road?\"\n",
    "        ),\n",
    "        ChatMessage(role=\"user\", content=\"I don't know, why?\"),\n",
    "    ]\n",
    ")\n",
    "\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9581413d",
   "metadata": {},
   "source": [
    "## Streaming"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6f4dbedf",
   "metadata": {},
   "source": [
    "### Using `stream_complete` endpoint"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "977ad99f",
   "metadata": {},
   "outputs": [],
   "source": [
    "import ads\n",
    "from llama_index.llms.oci_data_science import OCIDataScience\n",
    "\n",
    "ads.set_auth(auth=\"security_token\", profile=\"<replace-with-your-profile>\")\n",
    "\n",
    "llm = OCIDataScience(\n",
    "    model=\"odsc-llm\",\n",
    "    endpoint=\"https://<MD_OCID>/predict\",\n",
    ")\n",
    "\n",
    "for chunk in llm.stream_complete(\"Tell me a joke\"):\n",
    "    print(chunk.delta, end=\"\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38abd64d",
   "metadata": {},
   "source": [
    "### Using `stream_chat` endpoint"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fca03dac",
   "metadata": {},
   "outputs": [],
   "source": [
    "import ads\n",
    "from llama_index.llms.oci_data_science import OCIDataScience\n",
    "from llama_index.core.base.llms.types import ChatMessage\n",
    "\n",
    "ads.set_auth(auth=\"security_token\", profile=\"<replace-with-your-profile>\")\n",
    "\n",
    "llm = OCIDataScience(\n",
    "    model=\"odsc-llm\",\n",
    "    endpoint=\"https://<MD_OCID>/predict\",\n",
    ")\n",
    "response = llm.stream_chat(\n",
    "    [\n",
    "        ChatMessage(role=\"user\", content=\"Tell me a joke\"),\n",
    "        ChatMessage(\n",
    "            role=\"assistant\", content=\"Why did the chicken cross the road?\"\n",
    "        ),\n",
    "        ChatMessage(role=\"user\", content=\"I don't know, why?\"),\n",
    "    ]\n",
    ")\n",
    "\n",
    "for chunk in response:\n",
    "    print(chunk.delta, end=\"\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0b986d4e",
   "metadata": {},
   "source": [
    "## Async"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "42294b23",
   "metadata": {},
   "source": [
    "### Call `acomplete` with a prompt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d52768eb",
   "metadata": {},
   "outputs": [],
   "source": [
    "import ads\n",
    "from llama_index.llms.oci_data_science import OCIDataScience\n",
    "\n",
    "ads.set_auth(auth=\"security_token\", profile=\"<replace-with-your-profile>\")\n",
    "\n",
    "llm = OCIDataScience(\n",
    "    model=\"odsc-llm\",\n",
    "    endpoint=\"https://<MD_OCID>/predict\",\n",
    ")\n",
    "response = await llm.acomplete(\"Tell me a joke\")\n",
    "\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aad4d4cb",
   "metadata": {},
   "source": [
    "### Call `achat` with a list of messages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1416bacf",
   "metadata": {},
   "outputs": [],
   "source": [
    "import ads\n",
    "from llama_index.llms.oci_data_science import OCIDataScience\n",
    "from llama_index.core.base.llms.types import ChatMessage\n",
    "\n",
    "ads.set_auth(auth=\"security_token\", profile=\"<replace-with-your-profile>\")\n",
    "\n",
    "llm = OCIDataScience(\n",
    "    model=\"odsc-llm\",\n",
    "    endpoint=\"https://<MD_OCID>/predict\",\n",
    ")\n",
    "response = await llm.achat(\n",
    "    [\n",
    "        ChatMessage(role=\"user\", content=\"Tell me a joke\"),\n",
    "        ChatMessage(\n",
    "            role=\"assistant\", content=\"Why did the chicken cross the road?\"\n",
    "        ),\n",
    "        ChatMessage(role=\"user\", content=\"I don't know, why?\"),\n",
    "    ]\n",
    ")\n",
    "\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0da3c384",
   "metadata": {},
   "source": [
    "### Using `astream_complete` endpoint"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b392dc3a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import ads\n",
    "from llama_index.llms.oci_data_science import OCIDataScience\n",
    "\n",
    "ads.set_auth(auth=\"security_token\", profile=\"<replace-with-your-profile>\")\n",
    "\n",
    "llm = OCIDataScience(\n",
    "    model=\"odsc-llm\",\n",
    "    endpoint=\"https://<MD_OCID>/predict\",\n",
    ")\n",
    "\n",
    "async for chunk in await llm.astream_complete(\"Tell me a joke\"):\n",
    "    print(chunk.delta, end=\"\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c22e167a",
   "metadata": {},
   "source": [
    "### Using `astream_chat` endpoint"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "056daa3a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import ads\n",
    "from llama_index.llms.oci_data_science import OCIDataScience\n",
    "from llama_index.core.base.llms.types import ChatMessage\n",
    "\n",
    "ads.set_auth(auth=\"security_token\", profile=\"<replace-with-your-profile>\")\n",
    "\n",
    "llm = OCIDataScience(\n",
    "    model=\"odsc-llm\",\n",
    "    endpoint=\"https://<MD_OCID>/predict\",\n",
    ")\n",
    "response = await llm.stream_chat(\n",
    "    [\n",
    "        ChatMessage(role=\"user\", content=\"Tell me a joke\"),\n",
    "        ChatMessage(\n",
    "            role=\"assistant\", content=\"Why did the chicken cross the road?\"\n",
    "        ),\n",
    "        ChatMessage(role=\"user\", content=\"I don't know, why?\"),\n",
    "    ]\n",
    ")\n",
    "\n",
    "async for chunk in response:\n",
    "    print(chunk.delta, end=\"\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ed26b8a7",
   "metadata": {},
   "source": [
    "## Configure Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "42fa2409",
   "metadata": {},
   "outputs": [],
   "source": [
    "import ads\n",
    "from llama_index.llms.oci_data_science import OCIDataScience\n",
    "\n",
    "ads.set_auth(auth=\"security_token\", profile=\"<replace-with-your-profile>\")\n",
    "\n",
    "llm = OCIDataScience(\n",
    "    model=\"odsc-llm\",\n",
    "    endpoint=\"https://<MD_OCID>/predict\",\n",
    "    temperature=0.2,\n",
    "    max_tokens=500,\n",
    "    timeout=120,\n",
    "    context_window=2500,\n",
    "    additional_kwargs={\n",
    "        \"top_p\": 0.75,\n",
    "        \"logprobs\": True,\n",
    "        \"top_logprobs\": 3,\n",
    "    },\n",
    ")\n",
    "response = llm.chat(\n",
    "    [\n",
    "        ChatMessage(role=\"user\", content=\"Tell me a joke\"),\n",
    "    ]\n",
    ")\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "094b98c0",
   "metadata": {},
   "source": [
    "## Function Calling"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "63a1532a",
   "metadata": {},
   "source": [
    "The [AI Quick Actions](https://docs.oracle.com/en-us/iaas/data-science/using/ai-quick-actions.htm) offers prebuilt service containers that make deploying and serving a large language model very easy. Either one of vLLM (a high-throughput and memory-efficient inference and serving engine for LLMs) or TGI (a high-performance text generation server for the popular open-source LLMs) is used in the service container to host the model, the end point created supports the OpenAI API protocol. This allows the model deployment to be used as a drop-in replacement for applications using OpenAI API. If the deployed model supports function calling, then integration with LlamaIndex tools, through the predict_and_call function on the llm allows to attach any tools and let the LLM decide which tools to call (if any).\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "28b53563",
   "metadata": {},
   "outputs": [],
   "source": [
    "import ads\n",
    "from llama_index.llms.oci_data_science import OCIDataScience\n",
    "from llama_index.core.tools import FunctionTool\n",
    "\n",
    "ads.set_auth(auth=\"security_token\", profile=\"<replace-with-your-profile>\")\n",
    "\n",
    "llm = OCIDataScience(\n",
    "    model=\"odsc-llm\",\n",
    "    endpoint=\"https://<MD_OCID>/predict\",\n",
    "    temperature=0.2,\n",
    "    max_tokens=500,\n",
    "    timeout=120,\n",
    "    context_window=2500,\n",
    "    additional_kwargs={\n",
    "        \"top_p\": 0.75,\n",
    "        \"logprobs\": True,\n",
    "        \"top_logprobs\": 3,\n",
    "    },\n",
    ")\n",
    "\n",
    "\n",
    "def multiply(a: float, b: float) -> float:\n",
    "    print(f\"---> {a} * {b}\")\n",
    "    return a * b\n",
    "\n",
    "\n",
    "def add(a: float, b: float) -> float:\n",
    "    print(f\"---> {a} + {b}\")\n",
    "    return a + b\n",
    "\n",
    "\n",
    "def subtract(a: float, b: float) -> float:\n",
    "    print(f\"---> {a} - {b}\")\n",
    "    return a - b\n",
    "\n",
    "\n",
    "def divide(a: float, b: float) -> float:\n",
    "    print(f\"---> {a} / {b}\")\n",
    "    return a / b\n",
    "\n",
    "\n",
    "multiply_tool = FunctionTool.from_defaults(fn=multiply)\n",
    "add_tool = FunctionTool.from_defaults(fn=add)\n",
    "sub_tool = FunctionTool.from_defaults(fn=subtract)\n",
    "divide_tool = FunctionTool.from_defaults(fn=divide)\n",
    "\n",
    "response = llm.predict_and_call(\n",
    "    [multiply_tool, add_tool, sub_tool, divide_tool],\n",
    "    user_msg=\"Calculate the result of `8 + 2 - 6`.\",\n",
    "    verbose=True,\n",
    ")\n",
    "\n",
    "print(response)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2dc0829c",
   "metadata": {},
   "source": [
    "### Using `FunctionAgent`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "29fa7fb6",
   "metadata": {},
   "outputs": [],
   "source": [
    "import ads\n",
    "from llama_index.llms.oci_data_science import OCIDataScience\n",
    "from llama_index.core.tools import FunctionTool\n",
    "from llama_index.core.agent.workflow import FunctionAgent\n",
    "\n",
    "ads.set_auth(auth=\"security_token\", profile=\"<replace-with-your-profile>\")\n",
    "\n",
    "llm = OCIDataScience(\n",
    "    model=\"odsc-llm\",\n",
    "    endpoint=\"https://<MD_OCID>/predict\",\n",
    "    temperature=0.2,\n",
    "    max_tokens=500,\n",
    "    timeout=120,\n",
    "    context_window=2500,\n",
    "    additional_kwargs={\n",
    "        \"top_p\": 0.75,\n",
    "        \"logprobs\": True,\n",
    "        \"top_logprobs\": 3,\n",
    "    },\n",
    ")\n",
    "\n",
    "\n",
    "def multiply(a: float, b: float) -> float:\n",
    "    print(f\"---> {a} * {b}\")\n",
    "    return a * b\n",
    "\n",
    "\n",
    "def add(a: float, b: float) -> float:\n",
    "    print(f\"---> {a} + {b}\")\n",
    "    return a + b\n",
    "\n",
    "\n",
    "def subtract(a: float, b: float) -> float:\n",
    "    print(f\"---> {a} - {b}\")\n",
    "    return a - b\n",
    "\n",
    "\n",
    "def divide(a: float, b: float) -> float:\n",
    "    print(f\"---> {a} / {b}\")\n",
    "    return a / b\n",
    "\n",
    "\n",
    "multiply_tool = FunctionTool.from_defaults(fn=multiply)\n",
    "add_tool = FunctionTool.from_defaults(fn=add)\n",
    "sub_tool = FunctionTool.from_defaults(fn=subtract)\n",
    "divide_tool = FunctionTool.from_defaults(fn=divide)\n",
    "\n",
    "agent = FunctionAgent(\n",
    "    tools=[multiply_tool, add_tool, sub_tool, divide_tool],\n",
    "    llm=llm,\n",
    ")\n",
    "response = await agent.run(\n",
    "    \"Calculate the result of `8 + 2 - 6`. Use tools. Return the calculated result.\"\n",
    ")\n",
    "\n",
    "print(response)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
